package com.mtw.bbs.auth.provider;



import com.mtw.bbs.auth.pojo.PayloadData;
import com.mtw.bbs.auth.pojo.TokenInfo;
import com.mtw.bbs.auth.pojo.LoginForm;
import com.mtw.bbs.auth.utils.JwtTokenUtil;
import com.mtw.bbs.common.core.constant.AuthConstant;
import com.mtw.bbs.common.core.constant.ServiceConstant;
import com.mtw.bbs.common.core.enums.ResultCode;
import com.mtw.bbs.common.core.exception.AuthException;
import com.mtw.bbs.common.core.util.CommonUtil;
import com.mtw.bbs.common.core.vo.Result;
import com.mtw.bbs.common.redisBase.util.RedisUtilz;
import com.mtw.bbs.userAdmin.pojo.dto.UserDto;
import com.mtw.bbs.userAdmin.feign.UserClient;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 账号密码认证
 */
@Component
@AllArgsConstructor
public class PasswordTokenProvider implements TokenProvider {

    static final String GRANT_TYPE = "password";

	private UserClient userClient;
    private JwtTokenUtil jwtTokenUtil;
	private RedisUtilz<String, String> redisUtilz;



	@Override
	public TokenInfo authentication(LoginForm form) {

        // 获取验证码
        String uuid = form.getUuid();
        String code = form.getCode();
        if (StringUtils.isBlank(uuid) || StringUtils.isBlank(code)){
            throw new AuthException("验证码为空");
        }
        code = code.toLowerCase();

        String redisCode = redisUtilz.get(AuthConstant.CAPTCHA_CODE_PREFIX+uuid);
        if (redisCode == null || !redisCode.equalsIgnoreCase(code)){
            throw new AuthException("验证码错误");
        }


        // 验证用户
        Result<UserDto> result = userClient.loadUserByPassword(form.getUsername(), CommonUtil.getMD5(form.getPassword()));
        if (result.isFail()){
            throw new AuthException(result.getCode(),result.getMesg());
        }
        UserDto userDto = result.getData();
        if (userDto == null){
            throw new AuthException("账号不存在");
        }

        if (ServiceConstant.STATUS_DISABLE == userDto.getStatus()){
            throw new AuthException("账号已禁用");
        }

        // 添加负载
        PayloadData payloadData = new PayloadData();
        payloadData.setUsername(userDto.getUsername());
        payloadData.setClient(form.getPlatform());

        // 生成token
        String accessToken = jwtTokenUtil.crateJwtToken(payloadData, AuthConstant.ACCESS_TOKEN_KEY);
        String refreshToken = jwtTokenUtil.crateJwtToken(payloadData, AuthConstant.REFRESH_TOKEN_KEY);

        TokenInfo info = new TokenInfo();
        info.setAccessToken(accessToken);
        info.setRefreshToken(refreshToken);

        // redis缓存前缀
        String authKey =  AuthConstant.REDIS_AUTH_PREFIX+userDto.getUsername()+":"+form.getPlatform()+":";

        // 删除旧的key
        Set<String> keySet = redisUtilz.scan(authKey + "*");
        if (keySet != null && keySet.size() > 1){
            String oldKey = keySet.iterator().next();
            String oldRefreshToken = redisUtilz.get(oldKey);

            redisUtilz.delete(oldKey);
            if (StringUtils.isNotBlank(oldRefreshToken)){
                redisUtilz.delete(AuthConstant.REDIS_REFRESH_PREFIX+oldRefreshToken);
            }
        }

        // token存到redis
        redisUtilz.setForTimeCustom(authKey+accessToken,refreshToken,AuthConstant.EXPIRE_TIME_S, TimeUnit.SECONDS);
        redisUtilz.setForTimeCustom(AuthConstant.REDIS_REFRESH_PREFIX+refreshToken,accessToken,AuthConstant.REFRESH_TIME_S,TimeUnit.SECONDS);

        return info;
	}



    @Override
    public TokenInfo refresh(String accessToken ,String refreshToken) {

        boolean validated = jwtTokenUtil.validateJwtToken(refreshToken);
        if (!validated){
            throw new AuthException(ResultCode.AUTH_ERROR.getCode(),"无效token");
        }
        PayloadData payload = jwtTokenUtil.getPayload(refreshToken);
        // 获取用户
        Result<UserDto> result = userClient.loadUserByUserName(payload.getUsername());
        if (result.isFail()){
            throw new AuthException(result.getMesg());
        }
        // redis缓存前缀
        String authKey =  AuthConstant.REDIS_AUTH_PREFIX+payload.getUsername()+":"+payload.getClient()+":";
        // 删除旧缓存
        String oldAccessToken = redisUtilz.get(AuthConstant.REDIS_REFRESH_PREFIX + refreshToken);
        redisUtilz.delete(authKey+oldAccessToken);

        // 生成token
        String newToken = jwtTokenUtil.crateJwtToken(payload, AuthConstant.ACCESS_TOKEN_KEY);
        // token存到redis
        redisUtilz.setForTimeCustom(authKey+newToken,refreshToken,AuthConstant.EXPIRE_TIME_S, TimeUnit.SECONDS);
        redisUtilz.set(AuthConstant.REDIS_REFRESH_PREFIX+refreshToken,accessToken,0);


        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setAccessToken(newToken);
        return tokenInfo;
    }


    @Override
    public boolean logout(String token) {
        PayloadData payload;
        try {
            payload = jwtTokenUtil.getPayload(token);
        } catch (Exception e) {
            return false;
        }
        redisUtilz.delete(AuthConstant.REDIS_ACCESS_PREFIX+token);
        redisUtilz.delete(AuthConstant.REDIS_REFRESH_PREFIX+token);
        String authKey =  AuthConstant.REDIS_AUTH_PREFIX+payload.getUsername()+":"+payload.getClient()+":";
        redisUtilz.delete(authKey+token);
        return false;
    }

}
